import numpy as np
import scipy.interpolate as spi
import matplotlib.pyplot as plt
from utils.bspline_process import translation
from utils.utils2 import set0


def produce_x_BSpline(N=65, keep_decimals=False):
    tN = N
    x = np.power((1 - np.cos((np.arange(0, tN, 1)) * np.pi / (N - 1))), 2) / 4
    x1 = x * (-0.5) + 0.5
    x2 = x * 0.5 + 0.5
    res = np.concatenate([x1[::-1], x2], axis=0)

    return res


def produce_x_half(N=65):
    tN = N
    x = np.power((1 - np.cos((np.arange(0, tN, 1)) * np.pi / (N - 1))), 2) / 4

    return x


def produce_x_all(N=65):
    tN = 2 * N - 1
    x = np.power((1 - np.cos((np.arange(0, tN, 1) - (N - 1)) * np.pi / (N - 1))), 2) / 4

    return np.concatenate([x[0:N], x[N:2 * N - 1]], axis=0)

def produce_x(N=151):
    tN = 2 * N - 1
    x = np.power((1 - np.cos((np.arange(0, tN, 1) - (N - 1)) * np.pi / (N - 1))), 2) / 4
    x = x[0:N]
    # print(x)
    return np.concatenate([x[0:N-1], x[::-1]])

def Cubic_Spline_Interpolation(ordinates, x, N=65):
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    key = np.argmin(ordinates[:, 0])
    ordinates_up = ordinates[0:key + 1]
    ordinates_up = ordinates_up[::-1]
    ordinates_low = ordinates[key::]
    ipo3_u = spi.splrep(ordinates_up[:, 0], ordinates_up[:, 1], k=3)
    iy3_u = spi.splev(x[0:N], ipo3_u)

    ipo3_l = spi.splrep(ordinates_low[:, 0], ordinates_low[:, 1], k=3)
    iy3_l = spi.splev(x[N - 1::], ipo3_l)
    ordinates_interpoaltion = np.empty(shape=(2 * N - 1, 2))
    ordinates_interpoaltion[:, 0] = x
    ordinates_interpoaltion[0:N, 1] = iy3_u
    ordinates_interpoaltion[N::, 1] = iy3_l[1::]

    return ordinates_interpoaltion


def B_Spline_Interpolation(ordinates, fx, n=65, ctr=None):
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    np.set_printoptions(threshold=np.inf)

    x = ordinates[:, 0].flatten()
    y = ordinates[:, 1].flatten()
    tck, u = spi.splprep([x, y], s=0, per=0)
    xi, yi = spi.splev(fx, tck)
    ordinates_bspline = np.empty(shape=(len(xi), 2))
    ordinates_bspline[:, 0] = xi
    ordinates_bspline[:, 1] = yi
    ordinates_bspline_tmp = translation(ordinates_bspline)
    ordinates_bspline_tmp = set0(ordinates_bspline_tmp)
    equal_list = []
    for i in range(ordinates_bspline_tmp.shape[0] - 1):
        if ordinates_bspline_tmp[i, 0] == ordinates_bspline_tmp[i + 1, 0]:
            equal_list.append(i)
    ordinates_bspline_tmp = np.delete(ordinates_bspline_tmp, equal_list, axis=0)

    key = np.argmin(ordinates_bspline_tmp[:, 0])
    ordinates_CbSp_up = ordinates_bspline_tmp[0:key + 1]
    ordinates_CbSp_up = ordinates_CbSp_up[::-1]
    ordinates_CbSp_low = ordinates_bspline_tmp[key::]
    x_up = produce_x_half(N=n)
    x_low = produce_x_half(N=n)
    ordinates_CbSp = np.empty(shape=(n * 2 - 1, 2))
    ipo3_x = spi.splrep(ordinates_CbSp_up[:, 0], ordinates_CbSp_up[:, 1], k=3)
    ordinates_CbSp[0:n, 1] = spi.splev(x_up, ipo3_x)[::-1]
    ordinates_CbSp[0:n, 0] = x_up[::-1]
    ipo3_x = spi.splrep(ordinates_CbSp_low[:, 0], ordinates_CbSp_low[:, 1], k=3)
    ordinates_CbSp[n - 1::, 1] = spi.splev(x_low, ipo3_x)
    ordinates_CbSp[n - 1::, 0] = x_low

    return ordinates_CbSp
